package com.hccl.nlp;


import gate.creole.gazetteer.Lookup;

import java.io.Serializable;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

/**
 * Created by zhao on 2015/6/29.
 */
public class Trie {

    public static class CodeMap implements Serializable
    {
        int[] itemsKeys = null;
        Object[] itemsObjs = null;

        /**
         * resize the containers by one, leaving empty element at position 'index'
         */
        void resize(int index)
        {
            int newsz = itemsKeys.length + 1;
            int[] tempKeys = new int[newsz];
            Object[] tempObjs = new Object[newsz];
            System.arraycopy(itemsKeys, 0, tempKeys, 0, index);
            System.arraycopy(itemsObjs, 0, tempObjs, 0, index);
            System.arraycopy(itemsKeys, index, tempKeys, index + 1, newsz - index - 1);
            System.arraycopy(itemsObjs, index, tempObjs, index + 1, newsz - index - 1);

            itemsKeys = tempKeys;
            itemsObjs = tempObjs;
        } // resize

        /**
         * get the object from the map using the char key
         */
        Object get(int key)
        {
            if (itemsKeys == null) return null;
            int index = Arrays.binarySearch(itemsKeys, key);
            if (index<0)
                return null;
            return itemsObjs[index];
        }
        /**
         * put the object into the char map using the char as the key
         */
        Object put(int key, Object value)
        {
            if (itemsKeys == null)
            {
                itemsKeys = new int[1];
                itemsKeys[0] = key;
                itemsObjs = new Object[1];
                itemsObjs[0] = value;
                return value;
            }// if first time
            int index = Arrays.binarySearch(itemsKeys, key);
            if (index<0)
            {
                index = ~index;
                resize(index);
                itemsKeys[index] = key;
                itemsObjs[index] = value;
            }
            return itemsObjs[index];
        } // put

    }// class CharMap


    protected CodeMap transitionFunction = new CodeMap();

    public void put(int chr, Trie state) {
        transitionFunction.put(chr,state);
    }

    public Trie next(int chr) {//UnicodeType type){
        return (Trie)transitionFunction.get(chr);
    }

    public int[] getChars(){ return  transitionFunction.itemsKeys;}

    /** Checks whether this state is a final one
     */
    public boolean isFinal() {
// >>> was
//    return !lookupSet.isEmpty();
// >>> BOBI, Lookup opitimization
        if (lookupSet==null||codeStr==null)
            return false;
        return !lookupSet.isEmpty();
// >>> end
    }

    /** Returns a set of {@link Lookup} objects describing the types of lookups
     * the phrase for which this state is the final one belongs to
     */
    public Set getLookupSet(){return lookupSet;}

    /** Adds a new looup description to this state's lookup descriptions set
     */
    public void addLookup(Lookup lookup) {
// >>> was nothing
// >>> BOBI, Lookup opitimization
        if (lookupSet == null)
            lookupSet = new HashSet(4);
// >>> end

        lookupSet.add(lookup);
    } // addLookup

    /** Removes a looup description from this state's lookup descriptions set
     */
    public void removeLookup(Lookup lookup) {
        lookupSet.remove(lookup);
    } // removeLookup


    protected Set lookupSet;


    public String getCodeStr(){return codeStr;}

    public void addCodeStr(String str) {
        codeStr = str;
    }

    public Integer getMaxWordLen() {
        return maxWordLen;
    }

    public void setMaxWordLen(Integer maxWordLen) {
        this.maxWordLen = maxWordLen;
    }

    /** Removes a looup description from this state's lookup descriptions set
     */
    public void removeCodeStr() {
        codeStr=null;
    } // removeLookup


    protected String codeStr;

    protected Integer maxWordLen;


}